/*eslint-disable*/
const fs = require('fs')
const path = require('path')
const favicon = require('serve-favicon')
const express = require('express')
const compression = require('compression')
const proxy = require('http-proxy-middleware')

const { createBundleRenderer } = require('vue-server-renderer')

const app = express()
const port = 3004

//准备环境信息
let buildEnv = {
  build: 'test', //用于接口代理  test - 接口代理到测试环境 cp - 接口代理到tongkao100    production - 接口代理到tongkao100,静态资源引用cdn
  env: 'development' //用于打包代码的运行环境  development - 开发环境或不传   production - 测试环境或生产
}

try {
  buildEnv = JSON.parse(process.env.BUILD_OPTIONS)
} catch (e) {}

const isProd = buildEnv.env === 'production'

console.log(`start ${process.env.NODE_ENV || 'development'} server ！！！`)

//开始编译
//用来保存生成的renderer，分别为生产和开发环境
let renderer
//用于读取common.css，缓存其中的数据，不重复读取
// let commonCss = '';

if (isProd) {
  //生产环境下，直接使用dist中打包好的bundle，下面是创建服务端渲染的关键操作
  const serverBundle = require(path.resolve(
    __dirname,
    './wwwstatic/vue-ssr-server-bundle.json'
  ))
  const clientManifest = require(path.resolve(
    __dirname,
    './wwwstatic/vue-ssr-client-manifest.json'
  ))
  const template = fs.readFileSync(
    path.resolve(__dirname, './wwwstatic/template.ssr.html'),
    'utf-8'
  )

  renderer = createRenderer(serverBundle, {
    template,
    // inject: false,
    clientManifest,
    shouldPreload() {
      return false
    }, //去掉预加载
    shouldPrefetch() {
      return false
    } //去掉预加载
  })
} else {
  let templatePath = path.resolve(
    __dirname,
    './src/widget/template/template.ssr.html'
  )
  // 开发环境下，创建开发服务器进行热加载
  // 创建一个新的renderer，更新界面，不过需要界面刷新
  readyPromise = require('./build/setup-dev-server')(
    app,
    templatePath,
    (bundle, options) => {
      renderer = createRenderer(
        bundle,
        Object.assign(options, {
          // inject: false
        })
      )
    }
  )
}

//用于缓存静态资源，默认缓存30天
const serve = (filePath, cache) =>
  express.static(path.resolve(__dirname, filePath), {
    maxAge: cache && isProd ? 1000 * 60 * 60 * 24 * 30 : 0
  })

// app.use(favicon('./wwwstatic/logo.png'))
// app.use('/', serve(__dirname + '/wwwstatic', true))
app.use('/dist', serve('./dist', true))
app.use('/static', serve('./static', true)) //缓存静态资源
app.use(
  compression({
    threshold: 0
  })
) //gzip

//代理
app.use(
  '/',
  proxy('/local', {
    target: ['production', 'cp'].includes(buildEnv.build)
      ? 'https://www.novenblog.xin'
      : 'http://test.api.novenblog.xin', // 服务器地址
    changeOrigin: true,
    pathRewrite: {
      '^/local': ''
    }
  })
)

app.get(
  '*',
  isProd
    ? render
    : (req, res) => {
        readyPromise.then(() => render(req, res))
      }
)

//纯服务端执行的vue
app.listen(port, () =>
  console.log(`Server app listening http://localhost:${port} !`)
)

//推送给客户端的
function render(req, res) {
  if (req.url.includes('favicon')) {
    res.status(200).end()
    return
  }

  const context = {
    url: req.url
  }

  renderer
    .renderToString(context)
    .then(html => {
      res.writeHead(200, {
        'Content-Type': 'text/html;charset=utf-8'
      })

      res.status(200).end(html)
    })
    .catch(err => {
      res.status(500).end('Internal Server Error')
      console.log(err)
    })
}

//创建renderer
function createRenderer(bundle, options) {
  return createBundleRenderer(
    bundle,
    Object.assign(options, {
      runInNewContext: false
    })
  )
}
